package com.syni.mdd.sjb.common.component.utils.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @className RestTemplateUtils
 * @description rest请求封装类
 * @Author cfx
 * @DATE 2019/4/25 11:08
 * @VERSION 1.0
 **/
@Log4j2
@Component
public class RestTemplateUtils {


    private RestTemplateUtils(){
    }

    private static RestTemplate restTemplate;

    static {
        HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(2000);
        httpComponentsClientHttpRequestFactory.setConnectTimeout(2000);
        httpComponentsClientHttpRequestFactory.setReadTimeout(2000);
        restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
    }


    //开启了微服务的负载均衡的rest
    private static RestTemplate loadRestTemplate;

    /**
     * @Description 请求转发，只能转发post表单请求
     * @Param:
     * @return:
     * @Author: cfx
     * @Date: 2020/4/29
     */
    public static void forwardPost(String url, HttpServletRequest request, Map<String, String> params) {
        try {
            String method = request.getMethod();
            HttpMethod httpMethod = HttpMethod.resolve(method); // 1、封装请求头
            restTemplate.exchange(new URI(url),httpMethod,createRequestEntity(request,params), String.class);
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }

    private static HttpEntity createRequestEntity(HttpServletRequest request,Map params)
            throws URISyntaxException, IOException {
        MultiValueMap<String, String> headers = createRequestHeaders(request); // 2、封装请求体
        log.info("header:{}",JSON.toJSONString(headers));
        headers = new HttpHeaders();
        MultiValueMap multiValueMap = getParams(params);
        log.info("multiValueMap{}:",JSON.toJSONString(multiValueMap));
        HttpEntity httpEntity = new HttpEntity(multiValueMap, headers);
        return httpEntity;
    }

    private static MultiValueMap<String, String> createRequestHeaders(HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        List<String> headerNames = Collections.list(request.getHeaderNames());

        for (String headerName : headerNames) {
            List<String> headerValues = Collections.list(request.getHeaders(headerName));
            for (String headerValue : headerValues) {
                headers.add(headerName, headerValue);
            }
        }
        return headers;
    }

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        RestTemplateUtils.loadRestTemplate = restTemplate;
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(5000);
        httpComponentsClientHttpRequestFactory.setConnectTimeout(5000);
        httpComponentsClientHttpRequestFactory.setReadTimeout(5000);
        RestTemplate loadRestTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory);
        loadRestTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return loadRestTemplate;
    }

    public static RestTemplate getRestTemplate() {
        return restTemplate;
    }

    public static RestTemplate getLoadRestTemplate(){
        return loadRestTemplate;
    }

    /**
     * @ Description post请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntity(String url, Map<String,Object> params){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity httpEntity = new HttpEntity(getParams(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        log.info("responseBody:" + request.getBody());
        return request.getBody();
    }


    /**
     * @ Description post请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntityByLoadBalanced(String url, Map<String,Object> params){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity httpEntity = new HttpEntity(getParams(params), headers);
        ResponseEntity<String> request = loadRestTemplate.postForEntity(url,httpEntity,String.class);
        log.info("responseBody:" + request.getBody());
        return request.getBody();
    }

    public static String postForEntityByFile(String url,Map<String,Object> params){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity httpEntity = new HttpEntity(getParamsUpgrade(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        return request.getBody();
    }

    public static String postForEntityByFile(String url,Map<String,Object> params,RestTemplate restTemplate){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity httpEntity = new HttpEntity(getParamsUpgrade(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        return request.getBody();
    }

    /**
     * @ Description post请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntity(String url, Map<String,Object> params,Map<String,Object> headerMap){
        HttpHeaders headers = new HttpHeaders();
        headers.addAll(getParams(headerMap));
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity httpEntity = new HttpEntity(getParams(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        return request.getBody();
    }

    /**
     * @ Description post请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntity(RestTemplate thisRestTemplate ,String url, Map<String,Object> params,Map<String,Object> headerMap){
        log.info("请求url:" + url);
        log.info("请求参数:" + JSON.toJSONString(params));
        log.info("请求头参数:" + JSON.toJSONString(headerMap));
        HttpHeaders headers = new HttpHeaders();
        headers.addAll(getParams(headerMap));
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity httpEntity = new HttpEntity(getParams(params), headers);
        ResponseEntity<String> request = thisRestTemplate.postForEntity(url,httpEntity,String.class);
        log.info("url请求结果:{}",request.getBody());
        return request.getBody();
    }

    /**
     * @ Description post请求(json方式请求)
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntityForJson(String url,Object params){
        log.info("请求url:" + url);
        log.info("请求参数:" + JSON.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        log.info("url请求结果:{}",request.getBody());
        return request.getBody();
    }

    /**
     * @ Description post请求(json方式请求)
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntityForJson(RestTemplate restTemplate,String url,Object params){
        log.info("请求url:" + url);
        log.info("{}请求参数:{}",url,JSON.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        log.info("{}请求结果:{}",url,request.getBody());
        return request.getBody();
    }

    /**
     * @ Description post请求(json方式请求)
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntityForJson(String url,Object params,Map<String,Object> headerMap){
        log.info("请求url:" + url);
        log.info("请求参数:" + JSON.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.addAll(getParams(headerMap));
        HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(params), headers);
        ResponseEntity<String> request = restTemplate.postForEntity(url,httpEntity,String.class);
        log.info("url请求结果:{}",request.getBody());
        return request.getBody();
    }

    /**
     * @ Description post请求(json方式请求)
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntityForJsonByLoadBalanced(String url,Object params,Map<String,Object> headerMap){
        log.info("请求url:" + url);
        log.info("请求参数:" + JSON.toJSONString(params));
        log.info("请求头参数:" + JSON.toJSONString(headerMap, SerializerFeature.WriteMapNullValue));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.addAll(getParams(headerMap));
        HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(params), headers);
        ResponseEntity<String> request = loadRestTemplate.postForEntity(url,httpEntity,String.class);
        log.info("url请求结果:{}",request.getBody());
        return request.getBody();
    }

    /**
     * @ Description post请求(json方式请求)
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String postForEntityForJsonByLoadBalanced(String url,Object params){
        log.info("请求url:" + url);
        log.info("请求参数:" + JSON.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(params), headers);
        ResponseEntity<String> request = loadRestTemplate.postForEntity(url,httpEntity,String.class);
        log.info("url请求结果:{}",request.getBody());
        return request.getBody();
    }

    /**
     * @ Description post请求(json方式请求)
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ headerMap（请求头体，以map）
     * @ return json字符串
     */
    public static String postForEntityForJson(String url,HttpMethod method,Map<String,Object> headerMap,Object params){
        log.info("请求url:" + url);
        log.info("请求参数:" + JSON.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.addAll(getParams(headerMap));
        HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(params), headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url,method,httpEntity,String.class);
        log.info("url请求结果:{}",responseEntity.getBody());
        return responseEntity.getBody();
    }

    /**
     * @ Description get请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String getForEntity(String newUrl,Map<String,Object> params){
        log.info("请求url:" + newUrl);
        log.info("请求参数:" + JSON.toJSONString(params));
        List<String> paramsList = new ArrayList<>();
        if(params.size() > 0){
            for(Map.Entry paramEntry : params.entrySet()){
                paramsList.add(String.format("%s={%s}",paramEntry.getKey(),paramEntry.getKey()));
            }
        }

        if(paramsList.size() > 0) {
            newUrl = String.format("%s?%s", newUrl, StringUtils.join(paramsList, "&"));
        }
        ResponseEntity<String> stringResponseEntity = restTemplate.getForEntity(newUrl,String.class,params);
        log.info("url请求结果:{}",stringResponseEntity.getBody());
        return stringResponseEntity.getBody();
    }

    /**
     * @ Description get请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ headerMap (请求头参数)
     * @ return json字符串
     */
    public static String getForEntityWithHead(String newUrl, Map<String, Object> params, Map<String, Object> headerMap) {
        log.info("请求url:" + newUrl);
        log.info("请求参数:" + JSON.toJSONString(params));
        log.info("请求头参数:" + JSON.toJSONString(headerMap));
        List<String> paramsList = new ArrayList<>();
        if (params.size() > 0) {
            for (Map.Entry<String, Object> paramEntry : params.entrySet()) {
                paramsList.add(String.format("%s=%s", paramEntry.getKey(), paramEntry.getValue()));
            }
        }
        HttpHeaders headers = new HttpHeaders();
        headers.addAll(getParams(headerMap));
        HttpEntity httpEntity = new HttpEntity(headers);
        if (paramsList.size() > 0) {
            newUrl = String.format("%s?%s", newUrl, StringUtils.join(paramsList, "&"));
        }
        ResponseEntity<String> stringResponseEntity = loadRestTemplate.exchange(newUrl, HttpMethod.GET, httpEntity, String.class);
        log.info("url请求结果:{}",stringResponseEntity.getBody());
        return stringResponseEntity.getBody();
    }

    /**
     * @ Description get请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String getForEntity(RestTemplate cusRestTemplate,String newUrl,Map<String,Object> params){
        List<String> paramsList = new ArrayList<>();
        if(params.size() > 0){
            for(Map.Entry paramEntry : params.entrySet()){
                paramsList.add(String.format("%s={%s}",paramEntry.getKey(),paramEntry.getKey()));
            }
        }

        if(paramsList.size() > 0) {
            newUrl = String.format("%s?%s", newUrl, StringUtils.join(paramsList, "&"));
        }
        ResponseEntity<String> stringResponseEntity = cusRestTemplate.getForEntity(newUrl,String.class,params);
        return stringResponseEntity.getBody();
    }

    public static String getForEntity(RestTemplate customRestTemplate,String newUrl,Map<String,Object> params,Map<String,Object> headerMap){
        List<String> paramsList = new ArrayList<>();
        if(params.size() > 0){
            for(Map.Entry paramEntry : params.entrySet()){
                paramsList.add(String.format("%s=%s",paramEntry.getKey(),paramEntry.getValue()));
            }
        }
        HttpHeaders headers = new HttpHeaders();
        headers.addAll(getParams(headerMap));
        HttpEntity httpEntity = new HttpEntity(headers);
        if(paramsList.size() > 0) {
            newUrl = String.format("%s?%s", newUrl, StringUtils.join(paramsList, "&"));
        }
        ResponseEntity<String> stringResponseEntity = customRestTemplate.exchange(newUrl,HttpMethod.GET,httpEntity,String.class);
        return stringResponseEntity.getBody();
    }

    /**
     * @ Description get请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ headerMap (请求头参数)
     * @ return json字符串
     */
    public static String getForEntity(String newUrl,Map<String,Object> params,Map<String,Object> headerMap){
        List<String> paramsList = new ArrayList<>();
        if(params.size() > 0){
            for(Map.Entry paramEntry : params.entrySet()){
                paramsList.add(String.format("%s=%s",paramEntry.getKey(),paramEntry.getValue()));
            }
        }
        HttpHeaders headers = new HttpHeaders();
        headers.addAll(getParams(headerMap));
        HttpEntity httpEntity = new HttpEntity(headers);
        if(paramsList.size() > 0) {
            newUrl = String.format("%s?%s", newUrl, StringUtils.join(paramsList, "&"));
        }
        ResponseEntity<String> stringResponseEntity = restTemplate.exchange(newUrl,HttpMethod.GET,httpEntity,String.class);
        return stringResponseEntity.getBody();
    }



    /**
     * @ Description get请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    public static String getForEntity(String url){
        ResponseEntity<String> stringResponseEntity = restTemplate.getForEntity(url,String.class);
        return stringResponseEntity.getBody();
    }

    public static MultiValueMap getParams(Map<String,Object> params){
        MultiValueMap<String,String> multiValueMap = new LinkedMultiValueMap();
        if(params.size() > 0){
            for(Map.Entry entry : params.entrySet()) {
                if(entry != null && entry.getValue() != null) {
                    List<String> paramsBody = new ArrayList<>();
                    paramsBody.add(entry.getValue().toString());
                    multiValueMap.put(entry.getKey().toString(), paramsBody);
                }
            }
        }
        return multiValueMap;
    }



    public static MultiValueMap getParamsUpgrade(Map<String,Object> params){
        MultiValueMap<String,Object> multiValueMap = new LinkedMultiValueMap();
        if(params.size() > 0){
            for(Map.Entry entry : params.entrySet()) {
                List<Object> paramsBody = new ArrayList<>();
                paramsBody.add(entry.getValue());
                multiValueMap.put(entry.getKey().toString(),paramsBody);
            }
        }
        return multiValueMap;
    }

    public static String getParamsUrl(String url, Map<String, Object> rpcParams) {
        List<String> params = new LinkedList<>();
        for(Map.Entry paramEntry : rpcParams.entrySet()){
            params.add(String.format("%s=%s",paramEntry.getKey(),paramEntry.getValue()));
        }
        if(params.size() > 0) {
            url = String.format("%s?%s", url, StringUtils.join(params, "&"));
        }
        return url;
    }

    public static Map<String, Object> getSassHeader(String token) {
        Map<String,Object> headerMap = new HashMap<>();
        headerMap.put("client_id","dxshapp");
        headerMap.put("client_secret","dxshapp");
        headerMap.put("Authorization",token);
        return headerMap;
    }

    /**
     * @ Description get请求
     * @ param url （请求url）
     * @ param params (请求参数,以map的形式)
     * @ return json字符串
     */
    /*public static String getForEntity(String url,Map<String,Object> params){
        List<String> paramsList = new ArrayList<>();
        if(params.size() > 0){
            for(Map.Entry paramEntry : params.entrySet()){
                paramsList.add(String.format("%s={%s}",paramEntry.getKey(),paramEntry.getKey()));
            }
        }
        String newUrl = String.format("%s?%s",url, StringUtils.join(paramsList,"&"));
        ResponseEntity<String> stringResponseEntity = restTemplate.getForEntity(newUrl,String.class,params);
        return stringResponseEntity.getBody();
    }*/
}
